#ifndef _NFEVENTS_H_
#define _NFEVENTS_H_

#define ELP_API __declspec(dllexport)

/**
 *	Return status codes
 **/
typedef enum STATUS
{
	STATUS_FAIL = -1,
	STATUS_SUCCESS = 0,
	STATUS_INVALID_ENDPOINT_ID,
	STATUS_NOT_INITIALIZED,
	STATUS_IO_ERROR,
	STATUS_REBOOT_REQUIRED,
	STATUS_INVALID_PARAM
} STATUS;

typedef UINT_PTR ENDPOINT_ID;
#define MAX_ADDRESS_LENGTH 32

/**
 *	TCP connection properties
 **/
typedef UNALIGNED struct _TCP_CONN_INFO
{
	// Local address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
	unsigned char localAddress[MAX_ADDRESS_LENGTH];

	// Remote address as sockaddr_in for IPv4 and sockaddr_in6 for IPv6
	unsigned char remoteAddress[MAX_ADDRESS_LENGTH];
} TCP_CONN_INFO, *PTCP_CONN_INFO;

#ifndef _C_API
/////////////////////////////////////////////////////////////////////////////////////
// C++ API
/////////////////////////////////////////////////////////////////////////////////////
class IOCPService;
using LPIOCPService = IOCPService*;
class ELP_API TCPEventHandler
{
public:
	//
	// TCP events
	//
	virtual void onTcpAccept(LPIOCPService pIOCPService, ENDPOINT_ID id, PTCP_CONN_INFO pConnInfo) = 0;
	virtual void onTcpConnected(LPIOCPService pIOCPService, ENDPOINT_ID id, PTCP_CONN_INFO pConnInfo) = 0;
	virtual void onTcpClosed(LPIOCPService pIOCPService, ENDPOINT_ID id) = 0;
	virtual void onTcpReceive(LPIOCPService pIOCPService, ENDPOINT_ID id, LPWSABUF pWsaBuffer) = 0;
	virtual void onTcpCanSend(LPIOCPService pIOCPService, ENDPOINT_ID id) = 0;
};

#else

#ifdef WIN32
#define NFAPI_CC __cdecl
#else
#define NFAPI_CC
#endif

/////////////////////////////////////////////////////////////////////////////////////
// C API
/////////////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
extern "C"
{
#endif
typedef LPVOID LPIOCPService;
	// C analogue of the class TCPEventHandler (see the definition above)
	typedef struct _TCP_EventHandler
	{
		void(NFAPI_CC* onTcpAccept)(LPIOCPService pIOCPService, ENDPOINT_ID id, PTCP_CONN_INFO pConnInfo);
		void(NFAPI_CC* onTcpConnected)(LPIOCPService pIOCPService, ENDPOINT_ID id, PTCP_CONN_INFO pConnInfo);
		void(NFAPI_CC* onTcpClosed)(LPIOCPService pIOCPService, ENDPOINT_ID id);
		void(NFAPI_CC* onTcpReceive)(LPIOCPService pIOCPService, ENDPOINT_ID id, LPWSABUF pWsaBuffer);
		void(NFAPI_CC* onTcpCanSend)(LPIOCPService pIOCPService, ENDPOINT_ID id);
	} TCPEventHandler, *PTCPEventHandler;

#ifdef __cplusplus
}
#endif
#endif
#endif